/* vue */
import { defineComponent, toRefs, ref,reactive, watch, PropType, toRef, computed } from "vue";
/* scss */
import './style.scss';
/* util */
import { i18n } from '@src/locales';
/* entity */
import Field from '@model/entity/Field';
//@ts-ignore
import { codemirror } from 'vue-codemirror';
// 引入语法
import 'codemirror/mode/javascript/javascript.js';
// 引入主题
import 'codemirror/theme/base16-dark.css';

// import 'codemirror/lib/codemirror.css';
// import 'codemirror/addon/display/autorefresh.js';

// import "codemirror/addon/edit/matchbrackets.js";
// import "codemirror/addon/edit/closebrackets.js";
// import "codemirror/addon/hint/show-hint.js";
// import "codemirror/addon/hint/show-hint.css";

export default defineComponent({
  name: "cm-editor",
  props: {
    canInsertedFields: {
      type: Array as PropType<Field[]>,
      default: () => ([])
    },
    code: {
      type: String,
      default: () => ('')
    }
  },
  components: { codemirror },
  setup(props,{ emit }) {
    const { code } = toRefs(props);
    const newCode = ref('');
    const insertFields = ref([] as any);
    const { canInsertedFields } = toRefs(props);
    newCode.value = code.value;
  
    const codeMirrorOption = reactive({
      lineWrapping: true,
      autoCloseBrackets: true,
      tabSize: 4,
      styleActiveLine: true,
      lineNumbers: true,
      matchBrackets: true,
      line: true,
      autoRefresh: true,
      foldGutter: true,  // 可将对象折叠，与下面的gutters一起使用
      extraKeys: { "Alt-/": "autocomplete" },
      mode: 'text/javascript',
      hintOptions: {// 自定义提示选项
        completeSingle: false
      },
      specialCharPlaceholder: function (ch:any) {
        let token = document.createElement("span");
        let content = "";
        token.className = "cm-invalidchar";
        if (typeof content == "string") {
          token.appendChild(document.createTextNode(content));
        }
        token.title = "\\u" + ch.charCodeAt(0).toString(16);
        token.setAttribute("aria-label", token.title);
        return token;
      },
      matchTags: { bothTags: true },  // 将突出显示光标周围的标签
      gutters: [
        "CodeMirror-linenumbers",
        "CodeMirror-foldgutter",
        "CodeMirror-lint-markers",      // CodeMirror-lint-markers是实现语法报错功能
      ],
    });
    /** 修改代码数据 */
    const handleCodemirrorChange = (value: any) => {
      emit('handleCodemirrorChange', newCode.value, insertFields.value);
    };
    return {
      code,
      newCode,
      codeMirrorOption, 
      canInsertedFields,
      insertFields,
      handleCodemirrorChange,  
    };
  },
  methods: {
    /*** 插入字段 */
    handleInsertField(value: Field) {
      // 插入的表单字段(去重)
      if(this.insertFields.length == 0 || this.insertFields.some((item: Field)=>item.fieldName != value.fieldName)){
        this.insertFields.push(value);
      }
      const { codemirror } = this.$refs.cmEditor as any;
      //获取codemirror光标位置
      const pos = codemirror.getCursor();
      const insertPos = {
        line: pos.line,
        ch: pos.ch
      };
      const content = `form[qf_field('${value.displayName}$${value.fieldName}$')]`;
      // const dom = document.createElement("span");
      // dom.className = "cm-field insert-field-tag mg-0";
      // dom.setAttribute('data-id', value.fieldName);
      // if (!content) return;
      // dom.innerHTML = content;

      const endPos = { line: insertPos.line, ch: insertPos.ch + content.length };
      codemirror.replaceRange(content, insertPos);//先插入字符串
      //再对插入字符串进行标签制定（其实就是在codemirror中动态添加标签）
      // codemirror.markText(insertPos, endPos, {
      //   replacedWith: dom
      // });
    }
  },

  render() {
    return (
      <div class="code_editing_wrap">
        <div class="insert_field_heard">
          <p class="insert_field_msg">{ i18n.t('formSetting.jsCodeBlock.codingMsg1') }</p>
          <el-dropdown onCommand={this.handleInsertField} trigger="click"> 
            <span class='field'>{i18n.t('view.designer.workFlow.webHookNode.jsonBodyText')} <i class="iconfont icon-fdn-select"></i></span>
            <el-dropdown-menu slot="dropdown" class={'insert_field_menu'}>
              <div class='insert_field_item'>
                {this.canInsertedFields.map((item: Field, index: number) => (
                  <el-dropdown-item key={item.fieldName} command={item}>
                    {item.displayName}
                  </el-dropdown-item>
                ))}
              </div>
            </el-dropdown-menu>
          </el-dropdown>
        </div>
        <codemirror
          ref="cmEditor"
          vModel={this.newCode}
          options={this.codeMirrorOption}
          onChanges={(value: string) => this.handleCodemirrorChange(value)}
        />
        <p class="out-msg">{ i18n.t('formSetting.jsCodeBlock.codingMsg2') }</p>
      </div>
    );
  }
});